home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / comm / bbs / citsrc6K05.lha / msgadd.c < prev    next >
C/C++ Source or Header  |  1996-11-03  |  33KB  |  1,498 lines

  1. /*
  2.  *                              msgadd.c
  3.  *
  4.  * External Message handler.  For use with external OtherNet parsers.
  5.  */
  6. #define VIEWING (1)
  7. /*
  8.  *                              history
  9.  *
  10.  * 96Sep01 AFP  V1.5 -- support vortex checking and archiving by month & year
  11.  * 91Mar31 HAW  v1.4 -- support for virtual rooms.
  12.  * 90Aug13 HAW  v1.3 -- support for room archiving.
  13.  * 89Oct23 HAW  v1.2 -- support for incoming route mail.
  14.  * 88Nov05 HAW  Created.
  15.  */
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <math.h>
  19. #include <time.h>
  20. #include "ctdl.h"
  21. /*
  22.  *                              contents
  23.  *
  24.  */
  25.  
  26. #define TITLE           "C86Net Message Importer"
  27.  
  28. int debug_flag=0;
  29. int force_flag=0;
  30.  
  31. #define NO_ERROR        0
  32. #define BAD_ARGS        1
  33. #define BAD_TABLE       2
  34. #define NO_NODE         3
  35. #define FATAL           4
  36. #define LF_ERROR        5
  37.  
  38. int       crtColumn;
  39. extern CONFIG cfg;                /* Configuration variables      */
  40. extern MessageBuffer msgBuf;      /* The -sole- message buffer    */
  41. extern aRoom roomBuf;             /* Room buffer  */
  42. extern logBuffer logBuf;
  43. extern FILE *roomfl,
  44.          *logfl;
  45. extern int thisRoom;              /* Current room */
  46. extern rTable *roomTab;
  47. extern struct mBuf mFile1,
  48.           mFile2;
  49. extern NetTable *netTab;
  50. extern NetBuffer netBuf;
  51. extern NetBuffer netTemp;
  52. extern FILE *netfl;
  53. extern LogTable *logTab;
  54. extern int thisNet;               /* Current node in use  */
  55. extern char *APPEND_ANY;
  56. extern char *APPEND_TEXT;
  57. extern FILE *msgfl,
  58.          *msgfl2;
  59. FILE     *GlobalFd;
  60. int       RouteSlot;
  61. extern FILE *upfd;
  62. char      inNet = NORMAL_NET;
  63.  
  64. FILE     *netLog = stderr;
  65. char      logNetResults = TRUE;
  66. char      netDebug = TRUE;
  67.  
  68. SListBase MailForward =
  69. {NULL, NULL, NULL, NULL, NULL};
  70. SListBase Arch_base =
  71. {NULL, ChkNtoStr, NULL, FreeNtoStr, EatNMapStr};
  72. static char EOP = FALSE;
  73. char     *R_SH_MARK = "&&";
  74. char     *NON_LOC_NET = "%%";
  75. char     *LOC_NET = "++";
  76.  
  77. void      GenInit (void);
  78. void      Process (char *fn);
  79. int       GetOtherNetChar (void);
  80. int       VirtualShared (int NetNo, label name);
  81. int       VirtualExists (label name);
  82. void      SaveIt (void);
  83. int       FindRoom (label nm);
  84. int       FindNet (label nm, NetBuffer * netBuf);
  85. void      AddVirtualField (char field, char *contents);
  86. void      PutMessage (void);
  87. void      HandleRouted (void);
  88. void      AddField (int field, char *fValue);
  89. int       FindPos (void);
  90. void      VirtualHandle (void);
  91. int       MARecVirtualRoom (int VirtIndex);
  92. void      TranslateFilename (char *realfn, char *fn);
  93. void      netResult (char *);
  94. char      Check_Address(label mbaddr );
  95. void      Fix_Name(char *out, char *in);
  96.  
  97. int
  98. mPrintf (char *format,...)
  99. {
  100.   return 0;
  101. }       /* stub to quiet the linker */
  102.  
  103. /*
  104.  * crashout()
  105.  *
  106.  * Big error handler.
  107.  */
  108. void
  109. crashout (str)
  110.   char     *str;
  111. {
  112.   printf (str);
  113.   exit (FATAL);
  114. }
  115.  
  116. /*
  117.  * main()
  118.  *
  119.  * This is the main manager.
  120.  */
  121. int       main (int, char **);
  122. int
  123. main (argc, argv)
  124.   char    **argv;
  125.   int       argc;
  126. {
  127.   int       rover;
  128.   printf ("%s %s\n%s\n\n", TITLE, VERSION_NAME, COPYRIGHT);
  129.   if (argc < 3)
  130.     {
  131.       printf ("usage: MSGADD <options>  nodename file [ file ... ]\n");
  132.       printf (" options:  -f  == force adding of messages even if not shared\n");
  133.       printf ("           -d  == debug information \n");
  134.       printf ("\nEach file may contain one or more messages in C86Net format.\n");
  135.       exit (BAD_ARGS);
  136.     }
  137.   /**
  138.     First scan for any options.
  139.   **/
  140.   for( rover=1; rover < argc && argv[rover][0] == '-'; rover++)
  141.     {
  142.     if( argv[rover][1] == 'f' || argv[rover][1] == 'F' )force_flag = 1;
  143.     if( argv[rover][1] == 'd' || argv[rover][1] == 'D' )debug_flag = 1;
  144.     };
  145.   cfg.weAre = UTILITY;
  146.   if (!readSysTab (TRUE, TRUE))
  147.     {
  148.       exit (BAD_TABLE);
  149.     }
  150.  
  151.   if (access (LOCKFILE, 0) != -1)
  152.     {
  153.       printf ("Please do not run MsgAdd using Outside Commands.\n");
  154.       writeSysTab ();
  155.       exit (LF_ERROR);
  156.     }
  157.  
  158.   GenInit ();
  159.   VirtInit ();
  160.   VortexInit ();
  161.   InitVortexing ();
  162.  
  163.   /**
  164.     find the first non-option argument and use as
  165.     the node name
  166.   **/
  167.   for( rover=1; rover < argc && argv[rover][0] == '-'; rover++)
  168.     ;
  169.  
  170.   if (FindNet (argv[rover], &netBuf) == ERROR)
  171.     {
  172.       writeSysTab ();
  173.       printf ("Could not find node %s.\n", argv[rover]);
  174.       exit (NO_NODE);
  175.     };
  176.  
  177.   for (rover++ ; rover < argc; rover++)
  178.     if( argv[rover][0] != '-' )Process (argv[rover]);
  179.   strcpy(msgBuf.mbtext,"No Vortex Problems found\n");
  180.   FinVortexing ();      /* cleanup and report errors */
  181.   printf(msgBuf.mbtext);
  182.   UpdVirtStuff ();
  183.   writeSysTab ();
  184.  
  185.   return 0;
  186. }
  187.  
  188. /*
  189.  * GenInit()
  190.  *
  191.  * This is a general initialization routine.
  192.  */
  193. void
  194. GenInit ()
  195. {
  196.   SYS_FILE  fn;
  197.  
  198.   initNetBuf (&netBuf);
  199.   initNetBuf (&netTemp);
  200.   makeSysName (fn, "ctdlnet.sys", &cfg.netArea);
  201.   openFile (fn, &netfl);
  202.  
  203.   initRoomBuf (&roomBuf);
  204.   makeSysName (fn, "ctdlroom.sys", &cfg.roomArea);
  205.   openFile (fn, &roomfl);
  206.  
  207.   InitMsgBase ();
  208.  
  209.   initLogBuf (&logBuf);
  210.   makeSysName (fn, "ctdllog.sys", &cfg.logArea);
  211.   openFile (fn, &logfl);
  212.  
  213.   makeSysName (fn, "ctdlarch.sys", &cfg.roomArea);
  214.   MakeList (&Arch_base, fn, NULL);
  215. }
  216.  
  217. /*
  218.  * Process()
  219.  *
  220.  * This will process a file - read a file for all messages and stuff them
  221.  * into the message base.
  222.  */
  223. void
  224. Process (fn)
  225.   char     *fn;
  226. {
  227.   extern char *READ_ANY;
  228.  
  229.   if ((GlobalFd = fopen (fn, READ_ANY)) == NULL)
  230.     {
  231.       printf ("ERROR: Could not open %s.\n", fn);
  232.       return;
  233.     }
  234.  
  235.   while (getMessage (GetOtherNetChar, TRUE, TRUE, TRUE))
  236.     SaveIt ();
  237.  
  238.   fclose (GlobalFd);
  239. }
  240.  
  241. /*
  242.  * GetOtherNetChar()
  243.  *
  244.  * This gets a character for getMessage.
  245.  */
  246. int
  247. GetOtherNetChar ()
  248. {
  249.   int       c;
  250.  
  251.   c = getc (GlobalFd);
  252.   if (c == EOF)
  253.     return -1;
  254.   return c;
  255. }
  256.  
  257. /*
  258.  * SaveIt()
  259.  *
  260.  * This is charged with saving the message in the database.
  261.  *
  262.  * 1. If mail, must do recipient validation.
  263.  * 2. Must validate room.
  264.  */
  265. void
  266. SaveIt ()
  267. {
  268.   int       LogSlot,
  269.             RoomSlot,
  270.             place;
  271.   extern char *NON_LOC_NET,
  272.            *LOC_NET;
  273.   char     *fn,
  274.            *realfn;
  275.  
  276.   if( debug_flag )
  277.     {
  278.     printf ("mbauth =-%s-\t", msgBuf.mbauth);
  279.     printf ("mbroom =-%s-\n", msgBuf.mbroom);
  280.     printf ("mbdate =-%s-\t", msgBuf.mbdate);
  281.     printf ("mbtime =-%s-\n", msgBuf.mbtime);
  282.     printf ("mboname=-%s-\t", msgBuf.mboname);
  283.     printf ("mborig =-%s-\n", msgBuf.mborig);
  284.     printf ("mbto   =-%s-\t", msgBuf.mbto);
  285.     printf ("mbsrcId=-%s-\n", msgBuf.mbsrcId);
  286.     };
  287.   if (VirtualExists (msgBuf.mbroom) != ERROR)
  288.     {
  289.       VirtualHandle ();
  290.       return;
  291.     };
  292.  
  293.   if (Check_Address(msgBuf.mbaddr) != 0)
  294.     {
  295.       HandleRouted ();
  296.     }
  297.   else if (strCmpU (msgBuf.mbroom, "mail") == SAMESTRING)
  298.     {
  299.       if( strCmpU(msgBuf.mbto, "sysop") == SAMESTRING )
  300.         {
  301.         strcpy(msgBuf.mbto, cfg.SysopName);
  302.         };
  303.       if ((LogSlot = findPerson (msgBuf.mbto, &logBuf)) == ERROR)
  304.         {
  305.           printf ("Could not deliver Mail to '%s', does not exist.\n",
  306.                   msgBuf.mbto);
  307.           return;
  308.         }
  309.       noteAMessage (logBuf.lbMail, MAILSLOTS, cfg.newest + 1, cfg.catSector);
  310.       putLog (&logBuf, LogSlot);
  311.     }
  312.   else
  313.     {
  314.       if ((RoomSlot = FindRoom (msgBuf.mbroom)) == ERROR)
  315.         {
  316.           printf ("Message meant for non-existent room '%s' not incorporated.\n",
  317.                   msgBuf.mbroom);
  318.           return;
  319.         };
  320.       if( debug_flag ) printf(" RoomSlot:%d\n",RoomSlot);
  321.       if (!NotVortex ())
  322.         {
  323.           printf ("Vortex detected, message is a duplicate, not incorporated.\n");
  324.           printf ("Author:%20s   ", msgBuf.mbauth);
  325.           printf ("Room:%s\n", msgBuf.mbroom);
  326.           printf ("  date:%20s   ", msgBuf.mbdate);
  327.           printf ("time:%s\n", msgBuf.mbtime);
  328.           printf (" Oname:%20s   ", msgBuf.mboname);
  329.           printf ("orig:%s\n", msgBuf.mborig);
  330.           printf ("    to:%20s   ", msgBuf.mbto);
  331.           printf (" src:%s\n\n", msgBuf.mbsrcId);
  332.           return;
  333.         };
  334.       if ((place = FindPos ()) == ERROR)
  335.         {
  336.         printf ("WARNING: msg for %s is not formally shared, discarded.\n",
  337.                 msgBuf.mbroom);
  338.         return;
  339.         };
  340.       noteAMessage (roomBuf.msg, MSGSPERRM, cfg.newest + 1, cfg.catSector);
  341.       roomTab[RoomSlot].rtlastMessage = cfg.newest + 1;
  342.       putRoom (RoomSlot);
  343.       if (roomBuf.rbShareType != PEON &&
  344.           netBuf.netRooms[place].mode != PEON)
  345.         strCpy (msgBuf.mbaddr, NON_LOC_NET);
  346.       else
  347.         strCpy (msgBuf.mbaddr, LOC_NET);
  348.  
  349.       if (roomBuf.rbflags.ARCHIVE == 1)
  350.         {
  351.           fn = SearchList (&Arch_base, NtoStrInit (thisRoom, "", 0, TRUE));
  352.           realfn = GetDynamic (strlen (fn) + 15);
  353.           TranslateFilename (realfn, fn);
  354.           if( debug_flag ) printf(" Filename;%s is now %s\n",fn,realfn);
  355.           if ((upfd = fopen (realfn, APPEND_TEXT)) != NULL)
  356.             {
  357.               if (msgBuf.mbdate[0])fprintf (upfd, "   %s ", msgBuf.mbdate);
  358.               if (msgBuf.mbtime[0] && sendTime)fprintf (upfd, "%s ", msgBuf.mbtime);
  359.               if (msgBuf.mbauth[0]) fprintf (upfd, "from %s", msgBuf.mbauth);
  360.               NormStr (msgBuf.mboname);
  361.               if (msgBuf.mboname[0])
  362.                 {
  363.                   fprintf (upfd, " @ %s", msgBuf.mboname);
  364.                   if (msgBuf.mbdomain[0])fprintf (upfd, cfg.DomainDisplay, msgBuf.mbdomain);
  365.                 };
  366.  
  367.               if (msgBuf.mbto[0]) fprintf (upfd, " to %s", msgBuf.mbto);
  368.               crtColumn = 1;
  369.               mFormat (msgBuf.mbtext);
  370.               fprintf (upfd, "\n");
  371.               fclose (upfd);
  372.             };
  373.           free(realfn);
  374.         }
  375.     }
  376.   /**  probably don't need this... strCpy (msgBuf.mborig, netBuf.netId); **/
  377.   PutMessage ();
  378.   cfg.newest++;
  379.  
  380.   cfg.catSector = mFile1.thisSector;
  381.   cfg.catChar = mFile1.thisChar;
  382. }
  383.  
  384. SListBase FwdAliasii;             /* keeps some other stuff happy */
  385. char      onConsole = FALSE,
  386.           remoteSysop = FALSE;
  387. int       callSlot = ERROR;
  388.  
  389. /*
  390.  * HandleRouted()
  391.  *
  392.  * This should handle mail routing incoming.
  393.  */
  394. void
  395. HandleRouted ()
  396. {
  397.   char     *AltName;
  398.   label     Name,
  399.             Id,
  400.             temp;
  401.   SYS_FILE  fn;
  402.   extern void (*NetPrintTarget) (char *fmt,...);
  403.   extern int (*ToFileWork) ();
  404.  
  405. /* no find? */
  406.   if ((RouteSlot = FindNet (msgBuf.mbaddr, &netTemp)) == ERROR)
  407.     {
  408.       return;
  409.     }
  410.  
  411. /* yes, found, data in netTemp - will we do the routing? */
  412.   if (!cfg.BoolFlags.RouteMail || !netTemp.nbflags.RouteTo)
  413.     {
  414.       return;
  415.     }
  416.  
  417. /* yes, we'll do the routing.  Now to figure it out. */
  418.   strCpy (Name, netTemp.netName);
  419.   strCpy (Id, netTemp.netId);
  420.  
  421.   if ((AltName = UseNetAlias (Name, TRUE)) != NULL)
  422.     strCpy (Name, AltName);
  423.  
  424.   if (FindRouteSlot () == ERROR)
  425.     {
  426.       return;
  427.     }
  428.  
  429. /* Ugly ugly kludge until we figure out how nbHiRouteInd is wrong */
  430.   if (netTemp.nbHiRouteInd < 0)
  431.     netTemp.nbHiRouteInd = 0;
  432.   sPrintf (temp, "R%d.%d", RouteSlot, netTemp.nbHiRouteInd++);
  433.  
  434.   makeSysName (fn, temp, &cfg.netArea);
  435.  
  436.   if ((upfd = safeopen (fn, APPEND_ANY)) == NULL)
  437.     {
  438.       return;
  439.     }
  440.  
  441.   fprintf (upfd, "%-20s", Id);
  442.   putc (0, upfd);
  443.   fprintf (upfd, "%-20s", Name);
  444.   putc (0, upfd);
  445.  
  446.   NetPrintTarget = ToFile;
  447.   StartEncode (putFLChar);
  448.   ToFileWork = Encode;
  449.   prNetStyle (TRUE, Encode, FALSE, "");
  450.   StopEncode ();
  451.   fclose (upfd);
  452.   netTemp.nbflags.HasRouted = TRUE;
  453.  
  454.   putNet (RouteSlot, &netTemp);
  455. }
  456.  
  457. /*
  458.  * findRoom()
  459.  *
  460.  * This function should find the named room.  Return ERROR if not found.
  461.  */
  462. int
  463. FindRoom (nm)
  464.   label     nm;
  465. {
  466.   int       rover;
  467.  
  468.   for (rover = 0; rover < MAXROOMS; rover++)
  469.     if (strCmpU (roomTab[rover].rtname, nm) == SAMESTRING)
  470.       {
  471.         getRoom (rover);
  472.         return rover;
  473.       }
  474.  
  475.   return ERROR;
  476. }
  477.  
  478. /*
  479.  * noteAMessage()
  480.  *
  481.  * This function notes a message in a message array.  Stolen from MSG.C.
  482.  */
  483. void
  484. noteAMessage (base, slots, id, loc)
  485.   MSG_NUMBER id;
  486.   SECTOR_ID loc;
  487.   theMessages *base;
  488.   int       slots;
  489. {
  490.   int       i;
  491.  
  492. /* store into current room: */
  493. /* slide message pointers down to make room for this one:       */
  494.   for (i = 0; i < slots - 1; i++)
  495.     {
  496.       base[i].rbmsgLoc = base[i + 1].rbmsgLoc;
  497.       base[i].rbmsgNo = base[i + 1].rbmsgNo;
  498.     }
  499.  
  500. /* slot this message in:    */
  501.   base[slots - 1].rbmsgNo = id;
  502.   base[slots - 1].rbmsgLoc = loc;
  503. }
  504.  
  505. /*
  506.  * FindNet()
  507.  *
  508.  * This function will find the named node.  Stolen from searchNameNet/NETMISC.
  509.  */
  510. int
  511. FindNet (label nm, NetBuffer * nBuf)
  512. {
  513.   int       rover;
  514.  
  515.   for (rover = 0; rover < cfg.netSize; rover++)
  516.     {
  517.       if (netTab[rover].ntflags.in_use &&
  518.           hash (nm) == netTab[rover].ntnmhash)
  519.         {
  520.           getNet (rover, nBuf);
  521.           if (strCmpU (nBuf->netName, nm) == SAMESTRING)
  522.             return rover;
  523.         }
  524.     }
  525.   return ERROR;
  526. }
  527.  
  528. /*
  529.  * FindPos()
  530.  *
  531.  * This finds the spot in the shared room array for the node that matches up
  532.  * with the current room.
  533.  */
  534. int
  535. FindPos ()
  536. {
  537.   int       rover;
  538.  
  539.   for (rover = 0; rover < SHARED_ROOMS; rover++)
  540.     if (isSharedRoom (thisNet, rover) &&
  541.         netRoomSlot (rover) == thisRoom &&
  542.         netGen (thisNet, rover) == roomBuf.rbgen)
  543.       return rover;
  544.  
  545.   return ERROR;
  546. }
  547.  
  548. /*
  549.  * VirtualHandle()
  550.  *
  551.  * This function will handle a message destined for a virt room.
  552.  */
  553. void
  554. VirtualHandle ()
  555. {
  556.   int       Vindex;
  557.  
  558.   if ((Vindex = VirtualShared (thisNet, msgBuf.mbroom)) == ERROR)
  559.     {
  560.       printf ("Virtual room %s not shared with %s, message not saved.\n",
  561.               msgBuf.mbroom, netBuf.netName);
  562.       return;
  563.     }
  564.   MARecVirtualRoom (Vindex);
  565. }
  566.  
  567. /*********** These functions stolen & modified from VIRT2.C ***************/
  568.  
  569. extern VirtualRoom *VRoomTab;
  570. extern VirtNet *VirtNetList;
  571. extern int VirtSize,
  572.           VNetSize;
  573.  
  574. /*
  575.  * MARecVirtualRoom()
  576.  *
  577.  * This function receives a virtual room from another system.
  578.  */
  579. int
  580. MARecVirtualRoom (int VirtIndex)
  581. {
  582.   int       VirtNo;
  583.   MSG_NUMBER rover;
  584.   char     *distance,
  585.             fn[50];
  586.   extern FILE *upfd;
  587.   extern char *WRITE_ANY;
  588.  
  589.   VirtNo = VirtNetList[thisNet].VirtList[VirtIndex].WhichVirt;
  590.  
  591.   if (VirtNetList[thisNet].VirtList[VirtIndex].mode != PEON)
  592.     {
  593.       distance = LD_DIR;
  594.       rover = VRoomTab[VirtNo].vrHiLD + 1l;
  595.       VRoomTab[VirtNo].vrChanged |= LD_CHANGE;
  596.     }
  597.   else
  598.     {
  599.       distance = LOCAL_DIR;
  600.       rover = VRoomTab[VirtNo].vrHiLocal + 1l;
  601.       VRoomTab[VirtNo].vrChanged |= LOC_CHANGE;
  602.     }
  603.   CreateVAName (fn, VirtNo, distance, rover);
  604.  
  605.   if ((upfd = fopen (fn, WRITE_ANY)) != NULL)
  606.     {
  607.       if (msgBuf.mbauth[0])
  608.         AddVirtualField ('A', msgBuf.mbauth);
  609.       if (msgBuf.mbdate[0])
  610.         AddVirtualField ('D', msgBuf.mbdate);
  611.       if (msgBuf.mbtime[0])
  612.         AddVirtualField ('C', msgBuf.mbtime);
  613.       if (msgBuf.mboname[0])
  614.         AddVirtualField ('N', msgBuf.mboname);
  615.       if (msgBuf.mborig[0])
  616.         AddVirtualField ('O', msgBuf.mborig);
  617.       if (msgBuf.mbroom[0])
  618.         AddVirtualField ('R', msgBuf.mbroom);
  619.       if (msgBuf.mbsrcId[0])
  620.         AddVirtualField ('S', msgBuf.mbsrcId);
  621.       if (msgBuf.mbto[0])
  622.         AddVirtualField ('T', msgBuf.mbto);
  623.       if (msgBuf.mbOther[0])
  624.         AddVirtualField ('P', msgBuf.mbOther);
  625.       if (msgBuf.mbdomain[0])
  626.         AddVirtualField ('X', msgBuf.mbdomain);
  627.       if (msgBuf.mbtext[0])
  628.         AddVirtualField ('M', msgBuf.mbtext);
  629.       fclose (upfd);
  630.     }
  631.   else
  632.     printf ("Unable to open %s!\n", fn);
  633.  
  634.   VirtSummary ();
  635.   return 0;
  636. }
  637.  
  638. /*
  639.  * AddVirtualField()
  640.  *
  641.  * This function adds a field to a virtual room message.
  642.  */
  643. void
  644. AddVirtualField (char field, char *contents)
  645. {
  646.   fprintf (upfd, "%c%s", field, contents);
  647.   fputc (0, upfd);
  648. }
  649.  
  650. /*
  651.  * VirtualExists()
  652.  *
  653.  * This function returns an index to given room, if exists.
  654.  */
  655. int
  656. VirtualExists (label name)
  657. {
  658.   int       rover;
  659.  
  660.   for (rover = 0; rover < VirtSize; rover++)
  661.     if (strCmpU (VRoomTab[rover].vrName, name) == SAMESTRING)
  662.       return rover;
  663.  
  664.   return ERROR;
  665. }
  666.  
  667. /*
  668.  * VirtualShared()
  669.  *
  670.  * This function returns an index into current net's virtual index.
  671.  */
  672. int
  673. VirtualShared (int NetNo, label name)
  674. {
  675.   int       rover,
  676.             VirtNo;
  677.  
  678.   if ((VirtNo = VirtualExists (name)) == ERROR)
  679.     return ERROR;
  680.  
  681.   for (rover = 0; rover < VIRT_LIMIT; rover++)
  682.     if (VirtNetList[NetNo].VirtList[rover].WhichVirt == VirtNo)
  683.       return rover;
  684.   return ERROR;
  685. }
  686.  
  687. /*********** These functions stolen & modified from MSG.C ***************/
  688.  
  689. /*
  690.  * doActualWrite()
  691.  *
  692.  * This should allow automatic bkp of msg file from RAM.
  693.  */
  694. char
  695. doActualWrite (FILE *whichmsg, struct mBuf *mFile, char c)
  696.   {
  697.   MSG_NUMBER temp;
  698.   int       toReturn = 0;
  699.  
  700.   if (mFile->sectBuf[mFile->thisChar] == 0xFF)
  701.     {
  702.  /* obliterating a msg   */
  703.       toReturn = 1;
  704.     }
  705.  
  706.   mFile->sectBuf[mFile->thisChar] = c;
  707.  
  708.   mFile->thisChar = ++mFile->thisChar % MSG_SECT_SIZE;
  709.  
  710.   if (mFile->thisChar == 0)
  711.     {   /* time to write sector out and get next: */
  712.       temp = mFile->thisSector;
  713.       temp *= MSG_SECT_SIZE;
  714.       fseek (whichmsg, temp, 0);
  715.       crypte (mFile->sectBuf, MSG_SECT_SIZE, 0);
  716.       if (fwrite (mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1)
  717.         {
  718.           crashout ("?putMsgChar-write fail");
  719.         }
  720.  
  721.       mFile->thisSector = ++mFile->thisSector % cfg.maxMSector;
  722.       temp = mFile->thisSector;
  723.       temp *= MSG_SECT_SIZE;
  724.       fseek (whichmsg, temp, 0);
  725.       if (fread (mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1)
  726.         {
  727.           crashout ("?putMsgChar-read fail");
  728.         }
  729.       crypte (mFile->sectBuf, MSG_SECT_SIZE, 0);
  730.     }
  731.   return (char) toReturn;
  732. }
  733.  
  734. /*
  735.  * doFlush()
  736.  *
  737.  * This will do actual writeup for specified msg file.
  738.  */
  739. void
  740. doFlush (whichmsg, mFile)
  741.   FILE     *whichmsg;
  742.   struct mBuf *mFile;
  743. {
  744.   long int  s;
  745.  
  746.   s = mFile->thisSector;
  747.   s *= MSG_SECT_SIZE;
  748.   fseek (whichmsg, s, 0);
  749.   crypte (mFile->sectBuf, MSG_SECT_SIZE, 0);
  750.   if (fwrite (mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1)
  751.     {
  752.       crashout ("?ctdlmsg.sys write fail");
  753.     }
  754.   crypte (mFile->sectBuf, MSG_SECT_SIZE, 0);
  755.   fflush (whichmsg);
  756. }
  757.  
  758. /*
  759.  * flushMsgBuf()
  760.  *
  761.  * This wraps up writing a message to disk, takes into account 2nd msg file if
  762.  * necessary.
  763.  */
  764. void
  765. flushMsgBuf ()
  766. {
  767.   doFlush (msgfl, &mFile1);
  768.   if (cfg.BoolFlags.mirror)
  769.     doFlush (msgfl2, &mFile2);
  770. }
  771.  
  772. /*
  773.  * putMessage()
  774.  *
  775.  * This function stores a message to disk.
  776.  * Always called before noteMessage() -- newest not ++ed yet.
  777.  * Returns: TRUE on successful save, else FALSE
  778.  */
  779. void
  780. PutMessage ()
  781. {
  782.   char     temp[40];
  783.   extern char *ALL_LOCALS,
  784.            *WRITE_LOCALS;
  785.   extern char *R_SH_MARK,
  786.            *LOC_NET,
  787.            *NON_LOC_NET;
  788.   char     *s;
  789.  
  790.   startAt (msgfl, &mFile1, cfg.catSector, cfg.catChar);
  791. /* tell putMsgChar where to write   */
  792.   if (cfg.BoolFlags.mirror)
  793.     startAt (msgfl2, &mFile2, cfg.catSector, cfg.catChar);
  794.  
  795.   putMsgChar (0xFF);    /* start-of-message     */
  796.  
  797. /* write message ID */
  798.   sPrintf (temp, "%lu", cfg.newest + 1);
  799.   AddField (0, temp);
  800.  
  801. /* write date:      */
  802.   if (msgBuf.mbdate[0])
  803.     {
  804.       AddField ('D', msgBuf.mbdate);
  805.     }
  806.   else
  807.     {
  808.       AddField ('D', "????");
  809.     }
  810.  
  811. /* write time:      */
  812.   if (msgBuf.mbtime[0])
  813.     {
  814.       AddField ('C', msgBuf.mbtime);
  815.     }
  816.   else
  817.     {
  818.       AddField ('C', "!!!!");
  819.     }
  820.  
  821. /* write author's name out: */
  822.   if (msgBuf.mbauth[0])
  823.     {
  824.       AddField ('A', msgBuf.mbauth);
  825.     }
  826.  
  827. /* write room name out:     */
  828.   AddField ('R', msgBuf.mbroom);
  829.  
  830.   if (msgBuf.mbto[0])
  831.     {   /* private message -- write addressee   */
  832.       AddField ('T', msgBuf.mbto);
  833.     }
  834.  
  835.   if (msgBuf.mbaddr[0])
  836.     {   /* net message routing  */
  837.       if (strCmpU (msgBuf.mbaddr, R_SH_MARK) == SAMESTRING ||
  838.           strCmpU (msgBuf.mbaddr, NON_LOC_NET) == SAMESTRING)
  839.         {
  840.           AddField ('N', msgBuf.mboname);
  841.           if (msgBuf.mborig[0])
  842.             {
  843.               AddField ('O', msgBuf.mborig);
  844.             }
  845.           roomTab[thisRoom].rtlastNet = cfg.newest + 1;
  846.         }
  847.       else if (strCmpU (msgBuf.mbaddr, LOC_NET) == SAMESTRING)
  848.         {
  849.           AddField ('N', msgBuf.mboname);
  850.           if (msgBuf.mborig[0])
  851.             {
  852.               AddField ('O', msgBuf.mborig);
  853.             }
  854.         }
  855.  
  856.       sPrintf (temp, "%s%d", msgBuf.mbaddr, thisNet);
  857.       AddField ('Q', temp);
  858.     }
  859.   else
  860.     {
  861.       if (msgBuf.mboname[0])
  862.         {
  863.           AddField ('N', msgBuf.mboname);
  864.         }
  865.       if (msgBuf.mborig[0])
  866.         {
  867.           AddField ('O', msgBuf.mborig);
  868.         }
  869.     }
  870.  
  871.   if (msgBuf.mbdomain[0])
  872.     {
  873.       AddField ('X', msgBuf.mbdomain);
  874.     }
  875.  
  876.   if (msgBuf.mbsrcId[0])
  877.     {
  878.       AddField ('S', msgBuf.mbsrcId);
  879.     }
  880.  
  881.   if (msgBuf.mbOther[0])
  882.     {
  883.       AddField ('P', msgBuf.mbOther);
  884.     }
  885.  
  886. /* write message text by hand because it would overrun AddField buffer: */
  887.   putMsgChar ('M');     /* M-for-message.       */
  888.   for (s = msgBuf.mbtext; *s; s++)
  889.     putMsgChar (*s);
  890.  
  891.   putMsgChar (0);       /* null to end text     */
  892.   flushMsgBuf ();
  893.  
  894. }
  895.  
  896. /*
  897.  * AddField()
  898.  *
  899.  * This adds a field to the message base.
  900.  */
  901. void
  902. AddField (field, fValue)
  903.   int       field;
  904.   char     *fValue;
  905. {
  906.   int i=0;
  907.   if( debug_flag )
  908.     {
  909.     if( field)
  910.       printf("   %c:%s(",field, fValue);
  911.     else
  912.       printf("NULL:%s(",fValue);
  913.     };
  914.   if (field)
  915.     putMsgChar (field);
  916.   while (*fValue)
  917.     {
  918.     putMsgChar (*fValue++);
  919.     i++;
  920.     };
  921.   putMsgChar (0);       /* End field. */
  922.   if( debug_flag)printf("%d characters)\n", i);
  923. }
  924.  
  925. /*
  926.  * putMsgChar()
  927.  *
  928.  * This function writes successive message chars to disk.
  929.  * Globals:     thisChar=       thisSector=
  930.  * Returns:     ERROR if problems else TRUE.
  931.  */
  932. int
  933. putMsgChar (c)
  934.   int       c;
  935. {
  936.   int       toReturn;
  937.   int       count1,
  938.             count2;
  939.  
  940.   toReturn = TRUE;
  941.   count1 = doActualWrite (msgfl, &mFile1, c);
  942.   if (cfg.BoolFlags.mirror)
  943.     {
  944.       count2 = doActualWrite (msgfl2, &mFile2, c);
  945.       if (count1 != count2)
  946.         printf ("Mirror msg count discrepancy!");
  947.     }
  948.   if (count1)
  949.     ++cfg.oldest;
  950.   return toReturn;
  951. }
  952.  
  953. static label SearchResult;
  954. static char *SearchTarget,
  955.           GetAlias;
  956.  
  957. /*
  958.  * UseNetAlias()
  959.  *
  960.  * This function will find a usenet alias or the converse.
  961.  */
  962. char     *
  963. UseNetAlias (char *Name, char FindAlias)
  964. {
  965.   void     *EatTrans ();
  966.   SListBase Dummy =
  967.   {NULL, NULL, NULL, NULL, EatTrans};
  968.   SYS_FILE  fn;
  969.   char     *c;
  970.  
  971.   SearchResult[0] = 0;
  972.   SearchTarget = Name;
  973.   if (!FindAlias)
  974.     while ((c = strchr (Name, ' ')) != NULL)
  975.       *c = '_';
  976.   makeSysName (fn, "st-alias.sys", &cfg.roomArea);
  977.   GetAlias = FindAlias;
  978.   MakeList (&Dummy, fn, NULL);  /* CHEAT!  WHEEEEEE! */
  979.   if (strLen (SearchResult) == 0)
  980.     return NULL;
  981.   return SearchResult;
  982. }
  983.  
  984. /*
  985.  * EatTrans()
  986.  *
  987.  * This function will eat a line of for the alias mapping.
  988.  */
  989. void     *
  990. EatTrans (char *line)
  991. {
  992.   char     *c;
  993.  
  994.   if ((c = strchr (line, ' ')) != NULL)
  995.     {
  996.       *c = 0;
  997.       if (GetAlias)
  998.         {       /* check second field */
  999.           if (strCmpU (c + 1, SearchTarget) == SAMESTRING)
  1000.             {
  1001.               strCpy (SearchResult, line);
  1002.             }
  1003.         }
  1004.       else
  1005.         {       /* check first field */
  1006.           if (strCmpU (line, SearchTarget) == SAMESTRING)
  1007.             {
  1008.               strCpy (SearchResult, c + 1);
  1009.             }
  1010.         }
  1011.     }
  1012.   return NULL;
  1013. }
  1014.  
  1015. /*
  1016.  * FindRouteSlot()
  1017.  *
  1018.  * This function will find the slot of routing node.  If found, netTemp will
  1019.  * contain the new slot, as will RouteSlot.
  1020.  */
  1021. int
  1022. FindRouteSlot ()
  1023. {
  1024. /*
  1025.  * first check to see if we're the direct (final) link, either
  1026.  * expressly or because the route is outdated.
  1027.  */
  1028.   if (!DirectRoute (&netTemp))  /* expressly?   */
  1029.     getNet ((RouteSlot = netTemp.nbRoute), &netTemp);
  1030.  
  1031.   return RouteSlot;
  1032. }
  1033.  
  1034. /*
  1035.  * DirectRoute()
  1036.  *
  1037.  * This will discover if we directly or indirectly talk to this node.
  1038.  */
  1039. char
  1040. DirectRoute (NetBuffer * n)
  1041. {
  1042.   return (char) (n->nbRoute == -1 ||    /* expressly?   */
  1043.                  !netTab[n->nbRoute].ntflags.in_use ||  /* outdated?    */
  1044.                  netTab[n->nbRoute].ntGen != n->nbRouteGen);    /* outdated? */
  1045. }
  1046.  
  1047. /*
  1048.  * getNetChar()
  1049.  *
  1050.  * This gets a character from a network temporary file.
  1051.  */
  1052. int
  1053. getNetChar ()
  1054. {
  1055.   return -1;    /* actually, this should never be called.       */
  1056. }
  1057.  
  1058. /*
  1059.  * SepNameSystem()
  1060.  *
  1061.  * This will parse an Other Recipient spec.
  1062.  */
  1063. char
  1064. SepNameSystem (char *string, char *person, char *system, NetBuffer * buf)
  1065. {
  1066.   char     *c;
  1067.   int       n;
  1068.   char      work[NAMESIZE * 3];   /* should be sufficient */
  1069.  
  1070.   strCpy (work, string);
  1071.   if ((c = strchr (work, '@')) == NULL)
  1072.     return NOT_SYSTEM;
  1073.  
  1074. /* find leading spaces of "name @ system" format */
  1075.   for (n = 1; c[n] == ' ' && c[n]; n++)
  1076.     ;
  1077.  
  1078.   if (strLen (c + n) >= NAMESIZE)
  1079.     return BAD_FORMAT;
  1080.  
  1081.   strCpy (system, c + n);
  1082.   if (searchNameNet (c + n, buf) == ERROR)      /* bad - set signal of it */
  1083.     return NO_SYSTEM;
  1084.  
  1085.   *c = 0;
  1086.   CleanEnd (work);      /* kill trailing spaces */
  1087.   if (strLen (work) >= NAMESIZE)
  1088.     return BAD_FORMAT;
  1089.  
  1090.   strCpy (person, work);
  1091.  
  1092.   return IS_SYSTEM;
  1093. }
  1094.  
  1095. #define WeServe(x)      SearchList(&Serves, x)
  1096. extern SListBase Serves;
  1097.  
  1098. /*
  1099.  * LocalName()
  1100.  *
  1101.  * This takes a string of form <system> _ <domain> and attempts to discover if
  1102.  * this domain mapped system is actually a local.  This is used when we're
  1103.  * sending mail and are trying to find out if a Who Else override needs to be
  1104.  * generated.  Ugly kludge, but, hey, that's what programming's all about, eh?
  1105.  */
  1106. char     *
  1107. LocalName (char *system)
  1108. {
  1109.   char     *domain,
  1110.            *System;
  1111.  
  1112.   if ((domain = strchr (system, '_')) == NULL)
  1113.     return system;
  1114.   domain += 2;  /* always preceded by a space -- or so we assume */
  1115.  
  1116.   if (strCmpU (domain, cfg.codeBuf + cfg.nodeDomain) == SAMESTRING ||
  1117.       WeServe (domain) != NULL)
  1118.     {
  1119.       System = strdup (system);
  1120.       if ((domain = strchr (System, ' ')) == NULL)
  1121.         return system;  /* should never happen, though */
  1122.       *domain = NULL;
  1123.       if (searchNameNet (System, &netTemp) != ERROR)
  1124.         {
  1125.           free (System);
  1126.           return netTemp.netName;
  1127.         }
  1128.       free (System);
  1129.     }
  1130.   return system;
  1131. }
  1132.  
  1133. /*
  1134.  * mFormat()
  1135.  *
  1136.  * This function formats a string to modem and console.
  1137.  */
  1138. void
  1139. mFormat (char *string)
  1140. {
  1141.   char      wordBuf[MAXWORD];
  1142.   int       i;
  1143.  
  1144.   for (i = 0; string[i];)
  1145.     {
  1146.       i = getWord (wordBuf, string, i, MAXWORD);
  1147.       putWord (wordBuf);
  1148.     }
  1149. }
  1150.  
  1151. /*
  1152.  * getWord()
  1153.  *
  1154.  * This function fetches one word from current message.
  1155.  */
  1156. int
  1157. getWord (char *dest, char *source, int offset, int lim)
  1158. {
  1159.   int       i,
  1160.             j;
  1161.  
  1162. /* skip leading blanks if any */
  1163.   for (i = 0; source[offset + i] == ' ' && i < lim - 1; i++) ;
  1164.  
  1165. /* step over word */
  1166.   for (;
  1167.  
  1168.        source[offset + i] != ' ' &&
  1169.        i < lim - 1 &&
  1170.        source[offset + i] != 0;
  1171.  
  1172.        i++
  1173.     ) ;
  1174.  
  1175.   if (source[offset + i - 1] != '\n')
  1176.  
  1177. /* pick up any trailing blanks */
  1178.     for (; source[offset + i] == ' ' && i < lim - 1; i++) ;
  1179.  
  1180. /* copy word over */
  1181.   for (j = 0; j < i; j++)
  1182.     dest[j] = source[offset + j];
  1183.   dest[j] = 0;  /* null to tie off string */
  1184.  
  1185.   return (offset + i);
  1186. }
  1187.  
  1188. /*
  1189.  * putWord()
  1190.  *
  1191.  * This function writes one word to modem & console.
  1192.  */
  1193. void
  1194. putWord (char *st)
  1195. {
  1196.   char     *s;
  1197.   int       newColumn;
  1198.   static char prevChar = 0;
  1199.  
  1200.   for (newColumn = crtColumn, s = st; *s; s++)
  1201.     {
  1202.       if (*s != TAB)
  1203.         {
  1204.           if (*s == '\b')
  1205.             newColumn--;
  1206.           else
  1207.             ++newColumn;
  1208.         }
  1209.       else
  1210.         while (++newColumn % 8) ;
  1211.     }
  1212.   if (newColumn > termWidth)
  1213.     {
  1214.       fprintf (upfd, "\n");
  1215.       crtColumn = 1;
  1216.     }
  1217.  
  1218.   for (; *st; st++)
  1219.     {
  1220.  
  1221.       if (*st != TAB)
  1222.         {
  1223.           if (*st == '\b')
  1224.             crtColumn--;
  1225.           else
  1226.             ++crtColumn;
  1227.         }
  1228.       else
  1229.         while (++crtColumn % 8) ;
  1230.  
  1231.  /* worry about words longer than a line:        */
  1232.       if (crtColumn > termWidth)
  1233.         {
  1234.           fprintf (upfd, "\n");
  1235.           crtColumn = 1;
  1236.         }
  1237.  
  1238.       if (*st == '\n' && EOP)
  1239.         {
  1240.           fprintf (upfd, "\n");
  1241.           crtColumn = 1;
  1242.         }
  1243.       else if (prevChar != NEWLINE || (*st > ' '))
  1244.         {
  1245.           putc (*st, upfd);
  1246.           prevChar = *st;
  1247.           if (*st > ' ')
  1248.             EOP = FALSE;
  1249.         }
  1250.       else
  1251.         {
  1252.           fprintf (upfd, "\n");
  1253.           crtColumn = 1;
  1254.           if (*st == '\n' && !EOP)
  1255.             {
  1256.               fprintf (upfd, "\n");
  1257.               crtColumn = 1;
  1258.             }
  1259.           else
  1260.             putc (*st, upfd), prevChar = *st;
  1261.           EOP = TRUE;
  1262.         }
  1263.     }
  1264. }
  1265.  
  1266. /*
  1267.    * TranslateFilename()
  1268.    *
  1269.    * This does translations on a filename.  This is used for embedding dates
  1270.    * or numbers into a filename.
  1271.  */
  1272. void
  1273. TranslateFilename (char *realfn, char *fn)
  1274. {
  1275.   int       year,
  1276.             day,
  1277.             hours,
  1278.             minutes;
  1279.   char     *month;
  1280.  
  1281.   getCdate (&year, &month, &day, &hours, &minutes);
  1282.   *realfn = '\0';
  1283.   while (*fn)
  1284.     {
  1285.       if (*fn == '%')
  1286.         {
  1287.           fn++;
  1288.           switch (*fn)
  1289.             {
  1290.               case 'm':
  1291.               case 'M':
  1292.                 sPrintf (realfn, "%s", month);
  1293.                 realfn += 3;
  1294.                 break;
  1295.               case 'y':
  1296.               case 'Y':
  1297.                 sPrintf (realfn, "%d", year);
  1298.                 realfn += 2;
  1299.                 break;
  1300.             };
  1301.           fn++;
  1302.         }
  1303.       else
  1304.         {
  1305.           *realfn++ = *fn++;
  1306.         };
  1307.       *realfn = '\0';
  1308.     }
  1309. }
  1310.  
  1311. void
  1312. netResult (char *msg)
  1313. {
  1314.   printf ("%s\n", msg);
  1315. }
  1316.  
  1317. char     *MonthTab[] =
  1318. {
  1319.   "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
  1320.   "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
  1321.  
  1322. };
  1323.  
  1324. char     *KeyWords[] =
  1325. {
  1326.   "TODAY", "YESTERDAY"
  1327.  
  1328. };
  1329.  
  1330. char      DayPMonth[] =
  1331. {
  1332.   31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1333.  
  1334. };
  1335.  
  1336. /*
  1337.  * getCdate()
  1338.  *
  1339.  * This retrieves system date and returns in the parameters.
  1340.  */
  1341. void
  1342. getCdate (int *year, char **month, int *day, int *hours, int *minutes)
  1343. {
  1344.   int       mon,
  1345.             seconds,
  1346.             milli;
  1347.  
  1348.   getRawDate (year, &mon, day, hours, minutes, &seconds, &milli);
  1349.   *year -= 1900;
  1350.   *month = MonthTab[mon];
  1351.  
  1352. }
  1353.  
  1354. void      Do_Stack_Check (void);
  1355.  
  1356. #define LeapYear(x)     ((x % 4) ? FALSE : ((year % 100) ? TRUE : FALSE))
  1357. /************************************************************************/
  1358. /*      ReadDate() interprets the string and returns it in seconds      */
  1359. /************************************************************************/
  1360. int
  1361. ReadDate (char *date, long *RetTime)
  1362. {
  1363.   int       rover,
  1364.             found,
  1365.             keyword = -1;
  1366.   int       year,
  1367.             month,
  1368.             day,
  1369.             hours,
  1370.             minutes,
  1371.             seconds,
  1372.             milli;
  1373.   label     mon;
  1374.   char     *d = date;
  1375.   char      darray[6];            /* see format for utpack() */
  1376.  
  1377.   Do_Stack_Check ();
  1378.   if (strLen (date) == 0)
  1379.     return FALSE;
  1380.   if (isdigit (date[0]))
  1381.     {
  1382.       darray[0] = (char) (atoi (date) + 1900 - 1970);
  1383.       while (isdigit (*date))
  1384.         date++;
  1385.  
  1386.     }
  1387.   else
  1388.     {
  1389.       getRawDate (&year, &month, &day, &hours, &minutes,
  1390.                   &seconds, &milli);
  1391.       year -= 1970;
  1392.       darray[0] = (char) year;
  1393.       darray[1] = (char) month;
  1394.       darray[2] = (char) day;
  1395.  
  1396.     }
  1397.   for (rover = 0; isalpha (*date); date++, rover++)
  1398.     mon[rover] = toUpper (*date);
  1399.   mon[rover] = 0;
  1400.   if (rover == 0)
  1401.     {
  1402.       if (isdigit (d[0]))
  1403.         {
  1404.           *RetTime = CurAbsolute () - (atol (d) * 86400l);
  1405.           return TRUE;
  1406.         }
  1407.       return ERROR;
  1408.     };
  1409.   for (found = rover = 0; rover < NumElems (MonthTab); rover++)
  1410.     if (strncmp (mon, MonthTab[rover], strLen (mon)) == SAMESTRING)
  1411.       {
  1412.         found++;
  1413.         darray[1] = (char) (rover + 1);
  1414.  
  1415.       }
  1416.   if (found != 1)
  1417.     {
  1418.       for (keyword = -1, rover = 0; rover < NumElems (KeyWords); rover++)
  1419.         if (strncmp (mon, KeyWords[rover], strLen (mon)) == SAMESTRING)
  1420.           {
  1421.             keyword = rover;
  1422.  
  1423.           }
  1424.       if (keyword == -1)
  1425.         return ERROR;
  1426.       else
  1427.         {
  1428.           switch (keyword)
  1429.             {
  1430.               case 0:   /* TODAY */
  1431.                 break;
  1432.               case 1:   /* YESTERDAY */
  1433.                 --darray[2];
  1434.                 if (!darray[2])
  1435.                   {
  1436.                     --darray[1];
  1437.                     if (!darray[1])
  1438.                       {
  1439.                         darray[1] = 12;
  1440.                         --darray[0];
  1441.  
  1442.                       }
  1443.                     darray[2] = DayPMonth[darray[1] - 1];
  1444.                     if (darray[1] == 2 && LeapYear (darray[0]))
  1445.                       darray[2] = 29;
  1446.  
  1447.                   }
  1448.                 break;
  1449.  
  1450.             }
  1451.  
  1452.         }
  1453.  
  1454.     }
  1455.   if ((keyword == -1) && ((darray[2] = (char) atoi (date)) == 0))
  1456.     return ERROR;
  1457.   darray[3] = 0;
  1458.   darray[4] = 0;
  1459.   darray[5] = 0;
  1460.   *RetTime = utpack (darray);
  1461.   return TRUE;
  1462.  
  1463. }
  1464.  
  1465. /************************************************************************/
  1466. /*      CurAbsolute() current time in absolute terms.                   */
  1467. /************************************************************************/
  1468. long
  1469. CurAbsolute ()
  1470. {
  1471.   Do_Stack_Check ();
  1472.   return time (NULL);
  1473.  
  1474. }
  1475.  
  1476. /**
  1477.   Check Routing Address
  1478.  
  1479.   This function will check to see if we have a node address
  1480.   that is not ourselve, or NULL.
  1481. **/
  1482.  
  1483. char Check_Address(label mbaddr )
  1484.   {
  1485.   char new[20];
  1486.   char ours[20];
  1487.   if( strlen(mbaddr) == 0 ) return FALSE;
  1488.   /**
  1489.     Check to see if the node address is really ourselves
  1490.     or an alias...
  1491.   **/
  1492.   Fix_Name(new,  mbaddr);
  1493.   Fix_Name(ours, &cfg.codeBuf[cfg.nodeName]);
  1494.   if( strncmp(new, ours, strlen(ours)) == 0 )return FALSE;
  1495.   return TRUE;
  1496.   }
  1497.  
  1498.